import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Representa el personaje principal del juego el cual interactua con los emas objetos
 * 
 * @author (Ana Laura Hernandez Elias) 
 * @version (0.1)
 */

public class Duende extends Actor
{
  
    private boolean tocar;
    private WonderWorld castMundo;
    private GreenfootImage imParado;
    private GreenfootImage imPieIzq;
    private GreenfootImage imPieDer;
    private GreenfootImage imPieBrin;
    private GreenfootImage imParadoI;
    private GreenfootImage imPieIzqI;
    private GreenfootImage imPieDerI;
    private GreenfootImage imPieBrinI;
    
     private int  Pasos;//cantidad de pasos que dara
    private int jump=12; // cantidad que saltara
    private int cant=0;  //sirve para aumentar el salto
    private int acel=1; // aceleracion
    private boolean brinca; //indica si esta brincando o no
    private boolean inmune;
    private int accion; // indica si el personaje esta caminando
    private int dir; // indica direccion del personaje  izquierda o derecha
    static private final int DER=1;
    static private final int IZQ=0;
    private GreenfootImage imgAccion; 
    private boolean disparo;
    private SimpleTimer  reinicia;
    private SimpleTimer  sinInmunidad;
   
    private int mov; // validara si el personaje puede caminar o no
   
    
  /**
 * En el constructor se inicializan las variables que se utilizaran 
 */   
 public Duende(WonderWorld unMundo)
    {
        Pasos=0;
        imPieDer=new GreenfootImage("screen1_lw3.png");
        imParado=new GreenfootImage("screen1_lw2.png");
        imPieIzq=new GreenfootImage("screen1_lw1.png");
        imPieBrin=new GreenfootImage("screen1_lw4.png");
        
        imPieDerI=new GreenfootImage("screen1_lw3.png");
        imPieDerI.mirrorHorizontally();
        imParadoI=new GreenfootImage("screen1_lw2.png");
        imParadoI.mirrorHorizontally();
        imPieIzqI=new GreenfootImage("screen1_lw1.png");
        imPieIzqI.mirrorHorizontally();
        imPieBrinI=new GreenfootImage("screen1_lw4.png");
        imPieBrinI.mirrorHorizontally();
        
        accion=0;
        dir=DER;
        brinca=false;
        disparo=false;
        tocar=false;
        inmune=false;
        
        mov=0;
        castMundo=unMundo;
        reinicia=new SimpleTimer();
        sinInmunidad=new SimpleTimer();
        sinInmunidad.mark();
        reinicia.mark();
        
        
    }
 /**
 * En el actua se invocan los metodos que ponen en accion al personaje
 */
    
    public void act() 
    {
        if(getWorld()==null) return;
        mueveDuende();
        checaCaida();
        tocaBala();
        dispara();
        
        if(reinicia.millisElapsed()>1000)
           tocar=false;
  
        cambiaValorContador();
        inmunidad();
 
       if(castMundo.getVidas().getValue()==0)
         castMundo.PierdeJuego();
        
         if(getWorld()!=null)
            ganar(); 
            
         
        if(getWorld()!=null)
        {
          this.cambiaNivel();
          fall(); 
        }
        
        
       
     } 
     /**
 * en este metodo se le indica al personaje la direccion hacia donde se debe de mover, tambian se invoca al metodo de saltar
 */
 public void mueveDuende()
  {
      
       if(Greenfoot.isKeyDown("right") ||Greenfoot.isKeyDown("left"))
        {
         accion=1;
         if(Greenfoot.isKeyDown("right"))
         {
            if(getOneObjectAtOffset(36,37,Plataforma.class)==null)
            {
              ((WonderWorld) getWorld()).setMov(1);
              ((WonderWorld)getWorld()).setmvDer(true);
            }else ((WonderWorld) getWorld()).setmvDer(false);
           dir=DER;
         }
         if(Greenfoot.isKeyDown("left"))
         {
            if(((WonderWorld) getWorld()).getMov()>=0)
           {
           if(getOneObjectAtOffset(-36,37,Plataforma.class)==null)
            {
              ((WonderWorld)getWorld()).setMov(-1);
              ((WonderWorld)getWorld()).setmvIzq(true);
            }else ((WonderWorld) getWorld()).setmvIzq(false);
           }
          
           dir=IZQ;
          }
        }
        else accion=0;
      
       if(Greenfoot.isKeyDown("up"))
         {
             if(piso())
                brinca();
         }
           
       switch(accion)
         {
             case 0:parado();
             break;
             case 1: move();
             break;
         }
      
    }
 /**metodo donde el duende puede disparar 6 veces por cada bala que toque*/   
 public void dispara()
 {
   if(Greenfoot.isKeyDown("space"))
           {
       if(disparo==false&&castMundo.getBala().getValue()>0)
          {
             getWorld().addObject(new Bellota(dir),getX()+5,getY()+10);
             castMundo.getBala().add(-1);
             disparo=true;
         }
        }else disparo=false;   
 }
 /**metodo que otorga  6 disparos al personaje principal  */ 
 public void tocaBala()
    {
        
      if(this.isTouching(Bala.class))
         {
           //castMundo.getBala().setValue(castMundo.getBala().getValue()+6);
           castMundo.getBala().add(6);

           getWorld().removeObject(this.getOneIntersectingObject(Bala.class)) ; 
         } 
    }
  /**
 * Este metodo cambia el valor de los contadores que aparecen en el mundo, dependiendo de la clase que
 * toque el personaje , se le decrementan e incrementan vidas; y se incrementan puntos
 */   

 public void cambiaValorContador()
   {
      
           if(isTouching(Enemigo.class)&&tocar==false&&inmune==false) 
           {
             ((WonderWorld)getWorld()).getVidas().add(-1);
             tocar=true;
             reinicia.mark();
           }
   
           if(this.isTouching(Trebol.class))
           {
             castMundo.getVidas().add(1); 
             
             getWorld().removeObject(getOneIntersectingObject(Trebol.class));
             
            }
            
           if(this.isTouching(Moneda.class)) 
            {
                castMundo.getPuntos().add(1);  
                getWorld().removeObject(getOneIntersectingObject(Moneda.class));
            }
            
           if(this.isTouching(Olla.class)) 
            {
                castMundo.getPuntos().add(10);  
                getWorld().removeObject(getOneIntersectingObject(Olla.class));
                castMundo.getOlla().add(1);
            }
   }     
 /**
 * Este metodo  da el efecto de que el personaje esta caminando, hace que cambie la imagen cuando la variable
 * Pasos es mayor a 3 esta variable siempre se esta reiniciando
 */ 
   public void move()
     {
         Pasos++; 
          if(Pasos>=3)
           Pasos=0;
         CambiaImagen();
     }
  /**
 * Este metodo cambia la imagen del personaje a cuando esta parado
 */   
   public void parado()
    {
        CambiaImagen();
    }   
  /**
 * metodo que cambia la imagen para dar el efecto al personaje de que esta caminando
 */ 
    public void CambiaImagen()
    {
      if(accion==0)
        {
          if(dir==IZQ)
            imgAccion=imParadoI;
          else
            imgAccion=imParado;
        }
        
      if(accion==1)
        {
        switch(Pasos)
        {
            case 0: if(dir==DER)imgAccion=imPieDer;
                    else imgAccion=imPieDerI;
            break;
            case 1:if(dir==DER) imgAccion=imParado;
                   else imgAccion=imParadoI;
           break;
           case 2: if(dir==DER)imgAccion=imPieIzq;
                   else imgAccion=imPieIzqI;
           break;
           
        }  
       }
       
      if(brinca==true)
      {
        if(dir==DER)
        imgAccion= imPieBrin;
        else 
         imgAccion= imPieBrinI;
       }
      
      setImage(imgAccion);
    }  
  /**
 * metodo disminuye el valor en y
 */    
 public void caer()
    {
      
       setLocation(getX(), getY() + cant);   
       cant = cant + acel;  
       
       CambiaImagen();
       
   }
 
  /**
 * metodo que verifica si el personaje esta callendo o no
 */   
 public void checaCaida()
    {
     if(piso())
     {
       cant = 0;
       brinca=false;
    }
     else                    
       caer(); 
  }
 
   /**
 *
 *@retun regresa un true o un false 
 * Este metodo busca si abajo del personaje existe un piso o no si no lo encuentra el personaje
 */ 
 public boolean piso()
   {
    Actor busca = getOneObjectAtOffset( 0, getImage().getHeight()/2, Piso.class);
    if(busca==null)
         busca = getOneObjectAtOffset( getImage().getWidth()/2-1, getImage().getHeight()/2, Piso.class);
    if(busca==null)
     busca = getOneObjectAtOffset( -getImage().getWidth()/2+10, getImage().getHeight()/2, Piso.class);// busca si hay una plataforma  para no pasar entre ella
    return busca != null;
   }

   /**
 * Este metodo hace que el personaje aumente su valor en y
 */   
 public void brinca()
   {
       cant=-jump;
       brinca=true;
       caer();
   }
   /**
 * metodo que indica que se termino el nivel
 */
 public void cambiaNivel()
 {
     if(this.isTouching(GanaNivel.class)&&castMundo.getOlla().getValue()==3)
       {
           castMundo.cambiaNive();
           
           castMundo.getOlla().setValue(0);//cuentaOlla=0;
       }   
 }
 /**
  * indica si se gano el juego
  */
 public void ganar()
 {
      if(this.isTouching(GanaJuego.class))
         castMundo.ganar();
     
 }
 /** 
  * metodo que da o quita inmunidad al personaje dependiendo si toca una hada , esta le dara inmunidad por 5 segundos
  * cambia el valor del contador con el timpo que tiene de inmunidad
  */
 public void inmunidad()
 {
  if(this.isTouching(Hada.class))
    { 
       inmune=true;
       getWorld().removeObject(getOneIntersectingObject(Hada.class));
       castMundo.getInmunidad().setValue(5);
       sinInmunidad.mark();  
    }
 
  if(sinInmunidad.millisElapsed()>=5000)
  {
     inmune=false; 
     castMundo.getInmunidad().setValue(0);
    }
  else
  {
      int i=5-sinInmunidad.millisElapsed()/1000;
      castMundo.getInmunidad().setValue(i);
    }
    
 }
 /**
  * Verifica si el personaje callo en una trampa, si esto pasa invoca al metodo del mundo que reinicia el nivel en el que se encuentra y le
  * disminuye una vida
  */
 public void fall()
 {
  if(getY()>castMundo.getHeight())
   { 
       castMundo.reiniciaNivel();
       castMundo.getVidas().add(-1);
        this.setLocation(62,310);
   }
}
  
 
} 

